package cn.yunyichina.provider.pay.icbc.service.impl;

import java.io.InputStream;
import java.security.Security;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;

import cn.com.infosec.icbc.ReturnValue;
import cn.com.infosec.jce.provider.InfosecProvider;
import cn.yunyichina.provider.framework.utils.UUIDUtil;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.pay.icbc.BEOrderQueryResponse;
import cn.yunyichina.provider.iface.entity.pay.icbc.BEOrderQueryVo;
import cn.yunyichina.provider.iface.entity.pay.icbc.OrderQueryResponse;
import cn.yunyichina.provider.iface.entity.pay.icbc.OrderQueryVo;
import cn.yunyichina.provider.iface.entity.pay.icbc.RefundDataQueryResponse;
import cn.yunyichina.provider.iface.entity.pay.icbc.RefundDataQueryVo;
import cn.yunyichina.provider.iface.entity.pay.icbc.RefundDataResponse;
import cn.yunyichina.provider.iface.entity.pay.icbc.RefundDataVo;
import cn.yunyichina.provider.iface.entity.pay.icbc.TransferDataVo;
import cn.yunyichina.provider.iface.entity.pay.icbc.VerifyDataResponse;
import cn.yunyichina.provider.pay.icbc.constant.IcbcTrade;
import cn.yunyichina.provider.pay.icbc.constant.ResponseEnum;
import cn.yunyichina.provider.pay.icbc.entity.IcbcPayConfig;
import cn.yunyichina.provider.pay.icbc.service.BaseService;
import cn.yunyichina.provider.pay.icbc.service.IcbcWapService;
import cn.yunyichina.provider.pay.icbc.utils.PayUtil;
import cn.yunyichina.provider.pay.icbc.utils.Tools;
import cn.yunyichina.provider.pay.icbc.utils.XPathReader;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.ObjectParser;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 * 给旧系统调用的接口
 * @author zhangkewen
 *
 */
@Service
public class IcbcWapServiceImpl  extends BaseService implements IcbcWapService {
	  
	private static final Logger logger = LoggerFactory.getLogger(IcbcWapServiceImpl.class);
	 
	@Resource
	private Properties yaml;
	
	public ResCommon<String> icbcWapB2CPay(TransferDataVo vo) {
		logger.info("工行WAP支付->"+JSON.toJSONString(vo));
		ResCommon<String> response=new ResCommon<String>();
		
		try {
			IcbcPayConfig config=this.getConfig();
			config.setMerId(yaml.getProperty(IcbcTrade.ICBC_PAY_MERID));
			config.setMerAcct(yaml.getProperty(IcbcTrade.ICBC_PAY_MERACCT));
			config.setPrivateKeyPassword(yaml.getProperty(IcbcTrade.ICBC_PAY_PASSWORD));
			config.setSubmitUrl(yaml.getProperty(IcbcTrade.CONFIG_PAY_URL));
			
			if(StringUtils.isEmpty(vo.getNotifyUrl())){
				response.setResultCodeAndMessageAndResult(ResponseEnum.ICBC_NORMAL_EXCEPTION.getCode(), "商户通知地址不能为空!", null);
				return response;
			}
			
			//明文组包
			String merVar="";
			if(StringUtils.isEmpty(vo.getMerVar())){
				merVar="<merVAR></merVAR>";
			}else{
				merVar="<merVAR>"+vo.getMerVar()+"</merVAR>";
			}
			String str="<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\"?>"+
			"<B2CReq>"+
			"<interfaceName>"+config.getInterfaceName()+"</interfaceName>"+
			"<interfaceVersion>"+config.getInterfaceVersion()+"</interfaceVersion>"+
			"<orderInfo>"+
				"<orderDate>"+vo.getOrderDate()+"</orderDate>"+
				"<orderid>"+vo.getOrderNO()+"</orderid>"+
				"<amount>"+vo.getAmount().intValue()+"</amount>"+
				"<installmentTimes>"+config.getInstallmentTimes()+"</installmentTimes>"+
				"<curType>"+config.getCurType()+"</curType>"+
				"<merID>"+config.getMerId()+"</merID>"+
				"<merAcct>"+config.getMerAcct()+"</merAcct>"+
			"</orderInfo>"+
			"<custom>"+
				"<verifyJoinFlag>"+config.getVerifyJoinFlag()+"</verifyJoinFlag>"+
				"<Language>"+config.getLanguage()+"</Language>"+
			"</custom>"+
			"<message>"+
				"<goodsID></goodsID>"+
				"<goodsName></goodsName>"+
				"<goodsNum></goodsNum>"+
				"<carriageAmt></carriageAmt>"+
				"<merHint></merHint>"+
				"<remark1></remark1>"+
				"<remark2></remark2>"+
				"<merURL>"+vo.getNotifyUrl()+"</merURL>"+
				merVar+				
				"<notifyType>"+config.getNotifyType()+"</notifyType>"+
				"<resultType>"+config.getResultType()+"</resultType>"+
				"<backup1></backup1>"+
				"<backup2></backup2>"+
				"<backup3></backup3>"+
				"<backup4></backup4>"+
			"</message>"+
			"</B2CReq>";
			
			logger.info("工行WAP支付,请求明文:"+vo.getOrderNO()+"->"+str);
			
			//进行String对象字符串到byte的转换
			byte b[]=str.getBytes("GBK");
		
			//实例化工商银行对象
			ReturnValue rv = new ReturnValue();
			Security.addProvider( new InfosecProvider() );
			
			//对明文进行base编码 ************************************************************
			byte tranData[]=rv.base64enc(b);	
			String tranData_base=new String(tranData).replace("\r", "").replace("\n", "");
			logger.info("工行WAP支付,明文Base64后结果:"+vo.getOrderNO()+"->"+tranData_base);
			
			//计算
			int len=b.length;
			String p=config.getPrivateKeyPassword(); //证书密码
			char pass[]=p.toCharArray();
			String keyPath= "/cert/" + config.getMerId() + ".key";
			
			//读取文件流
			InputStream fis =IcbcWapServiceImpl.class.getResourceAsStream(keyPath);
			byte[] privateKey = new byte[fis.available()];
			fis.read(privateKey);
			fis.close();
			
			//对明文进行加密+base64编码,这里使用私钥算法 ************************************
			byte[] signResult=rv.sign(b,len,privateKey,pass);
			if(signResult==null){
				response.setResultCodeAndMessageAndResult(ResponseEnum.ICBC_NORMAL_EXCEPTION.getCode(), "签名异常，请排查是否icbc.jar包问题!", null);
				return response;
			}
			byte merSignMsg[]=rv.base64enc(signResult);
			
		   	String merSignMsg_base=new String(merSignMsg).replace("\r", "").replace("\n", "");					
		   	logger.info("工行WAP支付,签名结果:"+vo.getOrderNO()+"->"+merSignMsg_base);
		   	
			//商户公钥
			String publicPath="/cert/" + config.getMerId() + ".cer";
			fis = IcbcWapServiceImpl.class.getResourceAsStream(publicPath);;
			byte[] merCert = new byte[fis.available()];
			fis.read(merCert);
			fis.close();
			merCert=rv.base64enc(merCert);
			String merCert_base=new String(merCert).replace("\r", "").replace("\n", "");
			logger.info("工行WAP支付,公钥信息:"+vo.getOrderNO()+"->"+merCert_base);
			
			Map<String, String> postData=new HashMap<String,String>();
			postData.put("interfaceName", config.getInterfaceName());
			postData.put("interfaceVersion",config.getInterfaceVersion());
			postData.put("tranData", tranData_base);
			postData.put("merSignMsg", merSignMsg_base);
			postData.put("merCert", merCert_base);
			postData.put("clientType", "0");
			String returnHtml=PayUtil.createReturnHtml(postData, config.getSubmitUrl());
			logger.info("工行WAP支付,订单:"+vo.getOrderNO()+"生成HTML表格->"+returnHtml);
			response.setResultCodeAndMessageAndResult("0", "签名成功", returnHtml);
		} 
		catch(Exception e) {
			response.setResultCodeAndMessage(ResponseEnum.ICBC_NORMAL_EXCEPTION.getCode(), "工行WAP支付,订单签名发生异常:"+vo.getOrderNO()+"->"+e.getMessage());
			logger.error("工行WAP支付,订单签名发生异常:"+vo.getOrderNO()+"->"+e.getMessage(),e);
			e.printStackTrace();
		}
		
		return response;
	}
	
	public ResCommon<VerifyDataResponse> icbcWapB2CVerify(String notifyData,
			String signMsg) {

		ResCommon<VerifyDataResponse> response=new ResCommon<VerifyDataResponse>();
		
		try {
			logger.info("notifyData->" + notifyData+",signMsg->"+signMsg);
			// 进行String对象字符串到byte的转换
			byte notifyData_byte[] = ReturnValue.base64dec(notifyData.getBytes("GBK"));
			byte signMsg_byte[] = ReturnValue.base64dec(signMsg.getBytes("GBK"));

			// notifyData_src就是明文信息
			String notifyData_src = new String(notifyData_byte,"GBK");
			logger.info("明文" + notifyData_src);
			
			// 实例化工商银行对象
			ReturnValue rv = new ReturnValue();
			Security.addProvider(new InfosecProvider());

			// 读取证书
			String certPath = "/cert/admin.crt";
			InputStream fis = IcbcWapServiceImpl.class
					.getResourceAsStream(certPath);
			byte[] cert_byte = new byte[fis.available()];
			fis.read(cert_byte);
			fis.close();

			int verifyit = rv.verifySign(notifyData_byte,notifyData_byte.length, cert_byte, signMsg_byte); // 验签：返回0代表成功
			logger.info("验签结果：" + verifyit);
//			if(verifyit!=0){
//				response.setResultCodeAndMessage(ResponseEnum.ICBC_VERIFY_FAILURE.getMode(), "工行WAP支付通知,签名验证不通过!");
//				return response;
//			}
			
			//解释XML文件
			VerifyDataResponse dataResponse=new VerifyDataResponse();
			XPathReader reader=XPathReader.createXmlPathReaderByXml(notifyData_src);
			dataResponse.setAmount(ObjectParser.toInteger(reader.getText("/B2CRes/orderInfo/amount")));;
			dataResponse.setOrderDate(reader.getText("/B2CRes/orderInfo/orderDate"));
			dataResponse.setOrderNo(reader.getText("/B2CRes/orderInfo/orderid"));
			dataResponse.setMerAcct(reader.getText("/B2CRes/orderInfo/merAcct"));
			dataResponse.setMerId(reader.getText("/B2CRes/orderInfo/merID"));
			dataResponse.setNotifyDate(reader.getText("/B2CRes/bank/notifyDate"));
			dataResponse.setTranSerialNo(reader.getText("/B2CRes/bank/TranSerialNo"));
			dataResponse.setTranStat(ObjectParser.toInteger(reader.getText("/B2CRes/bank/tranStat")));
			dataResponse.setComment(reader.getText("/B2CRes/bank/comment"));
			response.setResultCodeAndMessageAndResult(ResponseEnum.SUCCESS.getCode(), "支付成功!", dataResponse);
			logger.info("工行WAP支付通知,订单验证签名返回->" + JSON.toJSONString(response));
		} catch (Exception e) {
			response.setResultCodeAndMessage(ResponseEnum.ICBC_NORMAL_EXCEPTION.getCode(), "工行WAP支付通知,订单验证签名发生异常:"+e.getMessage());
			logger.error("工行WAP支付通知,订单验证签名发生异常:"+e.getMessage(),e);
			e.printStackTrace();
		}
		
		return response;
	}
	
	public ResCommon<OrderQueryResponse> icbcWapB2COrderQuery(OrderQueryVo orderQueryVo) {
		
		logger.info("工行WAP支付查询->"+JSON.toJSONString(orderQueryVo));
		ResCommon<OrderQueryResponse> response=new ResCommon<OrderQueryResponse>();
		
		try {
			IcbcPayConfig config=this.getConfig();
			config.setMerId(yaml.getProperty(IcbcTrade.ICBC_PAY_MERID));
			config.setMerAcct(yaml.getProperty(IcbcTrade.ICBC_PAY_MERACCT));
			config.setPrivateKeyPassword(yaml.getProperty(IcbcTrade.ICBC_PAY_PASSWORD));
			config.setQueryUrl(yaml.getProperty(IcbcTrade.CONIFG_QUERY_URL));
			
			SSLSocketFactory ssf = null;
			OutputStreamWriter out = null;
			BufferedReader in = null;
			String result = "";

			try {
				// init context
				SSLContext ctx = SSLContext.getInstance("TLS");
				KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
				TrustManagerFactory tmf = TrustManagerFactory
						.getInstance("SunX509");
				KeyStore ks = KeyStore.getInstance("PKCS12");

				// load keystore
				String keyPath= "/cert/" + config.getMerId() + ".pfx";
				//读取文件流
				InputStream fis =IcbcWapServiceImpl.class.getResourceAsStream(keyPath);
				ks.load(fis, config.getPrivateKeyPassword().toCharArray());
				kmf.init(ks, config.getPrivateKeyPassword().toCharArray());
				ctx.init(kmf.getKeyManagers(), trustAllCerts, null);
				logger.info("工行WAP支付查询,加载密钥成功!");
				
				ssf = ctx.getSocketFactory();
				HttpsURLConnection.setDefaultSSLSocketFactory(ssf);
				HttpsURLConnection.setDefaultHostnameVerifier(hnv);
				URL realUrl = new URL(config.getQueryUrl());

				// 打开和URL之间的连接/servlet/ICBCINBSEBusinessServlet
				HttpsURLConnection conn = (HttpsURLConnection) realUrl
						.openConnection();

				// 设置通用的请求属性
				conn.setRequestProperty("accept", "*/*");
				conn.setRequestProperty("connection", "Keep-Alive");
				conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729");

				// 发送POST请求必须设置如下两行
				conn.setDoOutput(true);
				conn.setDoInput(true);

				// 获取URLConnection对象对应的输出流
				out = new OutputStreamWriter(conn.getOutputStream());

				// 发送请求参数
//				String data = "APIName=EAPI&APIVersion=001.001.025.001&MerReqData=";
//				String xml ="<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?>"+
//				"<ICBCAPI>"+
//				    "<in>"+
//				        "<tranDate>"+orderQueryVo.getOrderDate()+"</tranDate>"+
//				        "<ShopCode>"+config.getMerId()+"</ShopCode>"+
//				        "<ShopAccount>"+config.getMerAcct()+"</ShopAccount>"+
//				        "<orderList>"+
//				            "<orderNum>"+orderQueryVo.getOrderNO()+"</orderNum>"+
//				        "</orderList>"+
//				    "</in>"+
//			    "</ICBCAPI>";
				
				String data = "APIName=EAPI&APIVersion=001.001.002.001&MerReqData=";
				String xml = "<?xml  version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?>"
						+ "<ICBCAPI>"
						+ "<in>"
						+ "<orderNum>" + orderQueryVo.getOrderNO() + "</orderNum>"
						+ "<tranDate>" + orderQueryVo.getOrderDate() + "</tranDate>"
						+ "<ShopCode>" + config.getMerId() + "</ShopCode>"
						+ "<ShopAccount>" + config.getMerAcct() + "</ShopAccount>"
						+ "</in>"
						+ "</ICBCAPI>";
				
				data = data + xml;
				logger.info("工行WAP支付查询,请求数据->"+data);
				out.write(data);

				// flush输出流的缓冲
				out.flush();
				// 定义BufferedReader输入流来读取URL的响应
				in = new BufferedReader(
				new InputStreamReader(conn.getInputStream()));

				String line;
				while ((line = in.readLine()) != null) {
					result = result+ line;
				}

				result = java.net.URLDecoder.decode(result, "GB2312").trim();
				logger.info("工行WAP支付查询,查询结果->"+result);
				if(result.length()==5){
					String errorMessage=getIcbcErrorMessage(result);
					response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER_QUERY_FAILURE.getCode(), errorMessage);
					return response;
				}
				
				OrderQueryResponse orderQueryResponse=new OrderQueryResponse();
				XPathReader reader=XPathReader.createXmlPathReaderByXml(result);
				if(reader.findXPath("/ICBCAPI/out/tranSerialNum")){
					orderQueryResponse.setAmount(ObjectParser.toInteger(reader.getText("/ICBCAPI/out/amount")));
					orderQueryResponse.setOrderDate(orderQueryVo.getOrderDate());
					orderQueryResponse.setTranTime(reader.getText("/ICBCAPI/out/tranTime"));
					orderQueryResponse.setBankRem(reader.getText("/ICBCAPI/out/bankRem"));
					orderQueryResponse.setOrderNo(orderQueryVo.getOrderNO());
					orderQueryResponse.setTranSerialNum(reader.getText("/ICBCAPI/out/tranSerialNum"));
					orderQueryResponse.setTranStat(reader.getText("/ICBCAPI/out/tranStat"));
					response.setResultCodeAndMessageAndResult("0", "查询成功",orderQueryResponse);
				}else{
					response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER_QUERY_FAILURE.getCode(), "当笔订单没查询到");
				}
				
			} catch (Exception e) {
				logger.error("工行WAP支付查询,订单发生异常:"+e.getMessage(),e);
				response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER_QUERY_FAILURE.getCode(), "工行WAP支付查询,订单发生异常:"+e.getMessage());
				e.printStackTrace();
			}
			finally {
				try {
					if (out != null) {
						out.close();
					}
					if (in != null) {
						in.close();
					}
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
			
		}catch (Exception e) {
			response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER_QUERY_FAILURE.getCode(), "工行WAP支付查询:"+e.getMessage());
			logger.error("工行WAP支付查询,订单验证签名发生异常:"+e.getMessage(),e);
			e.printStackTrace();
		}
		
		return response;
	}
	
	/**
	 * 工行银企直连B2C退货
	 * @param refundDataVo
	 * @return
	 */
	public ResCommon<RefundDataResponse> icbcWapB2CRefund(
			RefundDataVo refundDataVo) {
		
		int returnFlag = 0;
		String sysout =""; //工行返回的信息
		ResCommon<RefundDataResponse> response=new ResCommon<RefundDataResponse>();
		
		try {
			IcbcPayConfig config=this.getConfig();
			config.setMerId(yaml.getProperty(IcbcTrade.ICBC_PAY_MERID));
			config.setMerAcct(yaml.getProperty(IcbcTrade.ICBC_PAY_MERACCT));
			config.setPayId(yaml.getProperty(IcbcTrade.ICBC_PAY_ID));
			config.setMerchantName(yaml.getProperty(IcbcTrade.ICBC_PAY_MERNAME));
			config.setPayCis(yaml.getProperty(IcbcTrade.ICBC_PAY_CIS));
			
			config .setNcIp(yaml.getProperty(IcbcTrade.CONFIG_NC_IP));
			config.setNcPort1(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT1));
			config.setNcPort2(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT2));
			String transCode="EBUSCOM";
			String sBankCode = "102";
			
			String sContent="<?xml version=\"1.0\" encoding = \"GBK\"?>"+
							"<CMS>"+
							"<eb>"+
							"<pub>"+
							"<TransCode>"+transCode+"</TransCode>"+
							"<CIS>"+config.getPayCis()+"</CIS>"+
							"<BankCode>"+sBankCode+"</BankCode>"+
							"<ID>"+config.getPayId()+"</ID>"+
							"<TranDate>"+refundDataVo.getTranDate()+"</TranDate>"+
							"<TranTime>"+refundDataVo.getTranTime()+"</TranTime>"+
							"<fSeqno>"+refundDataVo.getRefundOrderNo()+"</fSeqno>"+
							"</pub>"+
							"<in>"+
							"<TranType>0</TranType>"+
							"<ShopType>2</ShopType>"+
							"<ShopCode>"+config.getMerId()+"</ShopCode>"+
							"<ShopAcct>"+config.getMerAcct()+"</ShopAcct>"+
							"<OrderNum>"+refundDataVo.getOriginOrderNO()+"</OrderNum>"+
							"<PayType>1</PayType>"+
							"<PayDate>"+refundDataVo.getPayDate()+"</PayDate>"+
							"<TransferName></TransferName>"+
							"<TransferAccNo></TransferAccNo>"+
							"<PayAmt>"+refundDataVo.getPayAmount()+"</PayAmt>"+
							"<SignTime>"+refundDataVo.getSignTime()+"</SignTime>"+
							"<ReqReserved1></ReqReserved1>"+
							"<ReqReserved2></ReqReserved2>"+
							"</in>"+
							"</eb>"+
							"</CMS>";
			
			logger.info("工行银企直连退款"+refundDataVo.getOriginOrderNO()+"，明文->"+sContent);
			
			java.net.URL aURL =new java.net.URL("http://" + config.getNcIp() + ":" + config.getNcPort2());
			java.net.HttpURLConnection urlConnection =(java.net.HttpURLConnection) aURL.openConnection();
			urlConnection.setRequestMethod("POST");
			urlConnection.setDoInput(true);
			urlConnection.setDoOutput(true);
			urlConnection.setUseCaches(false);
			urlConnection.setRequestProperty("Content-Length",String.valueOf(sContent.getBytes("GBK").length));
			urlConnection.setRequestProperty("Content-Type","INFOSEC_SIGN/1.0");
			BufferedOutputStream out =new BufferedOutputStream(urlConnection.getOutputStream());		
			out.write(sContent.getBytes("GBK"));
			out.flush();
			out.close();
			urlConnection.connect();

			int responseCode = urlConnection.getResponseCode();
			if (responseCode != 200){
				response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER__FAILURE.getCode(), "工行退款签名失败");
				return response;
			}
				
			String resM = urlConnection.getResponseMessage();
			Thread.sleep(800);
			BufferedInputStream bbb =new BufferedInputStream(urlConnection.getInputStream());
			byte[] ccc = new byte[urlConnection.getContentLength()];
			bbb.read(ccc);
			logger.info("工行银企直连退款->接收签名端数据成功：" + new String(ccc,"gb2312"));
			
			String repContent = new String(ccc);
			repContent.replaceAll("\n","");			
			urlConnection.disconnect();			
			int beginSign = repContent.indexOf("<sign>") + 6;
			int endSign = repContent.indexOf("</sign>");
			String repSignContent =repContent.substring(beginSign, endSign);
			
			String urlStr1 = "http://" + config.getNcIp() + ":" + config.getNcPort1()+"/servlet/ICBCCMPAPIReqServlet?userID="
			+config.getPayId()+"&PackageID="
			+refundDataVo.getRefundOrderNo()+"&SendTime="
			+refundDataVo.getTranDate()+refundDataVo.getTranTime();
			
			HttpClient myclient = new HttpClient(); //构建http客户端	
			PostMethod mypost = new PostMethod(urlStr1); //加密端口
		
			mypost.addParameter("Version", "0.0.0.1");
			mypost.addParameter("TransCode", transCode);
			mypost.addParameter("BankCode", sBankCode);
			mypost.addParameter("GroupCIS", config.getPayCis());
			mypost.addParameter("ID", config.getPayId());
			mypost.addParameter("PackageID", refundDataVo.getRefundOrderNo());
			mypost.addParameter("Cert", "");
			mypost.addParameter("reqData", repSignContent);
			
			logger.info("工行银企直连退款"+refundDataVo.getOriginOrderNO()+"->开始发送到加密端...");
			returnFlag = myclient.executeMethod(mypost); //获得http返回码
			logger.info("工行银企直连退款"+refundDataVo.getOriginOrderNO()+"->已返回数据...");
			
			if(returnFlag!=200){
				response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER__FAILURE.getCode(), "工行退款发送到中转到服务器失败!");
				return response;
			}
			
			try {
				String postResult = mypost.getResponseBodyAsString();
				logger.info("工行银企直连退款"+refundDataVo.getOriginOrderNO()+"->返回数据如下:" + new String(postResult.getBytes("ISO8859-1"),"gb2312"));
				postResult = postResult.substring(8);
				byte[] decodeResult = Tools.getFromBASE64(postResult);
				sysout = new String(decodeResult,"GBK");
				logger.info("工行银企直连退款"+refundDataVo.getOriginOrderNO()+"->base64解码如下:" +sysout);

			} catch (Exception e) {
				logger.error("工行银企直连退款解释返回数据异常"+refundDataVo.getOriginOrderNO(),e);
				response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER__FAILURE.getCode(), "工行银企直连退款解释返回数据异常!");
				return response;
			}
			mypost.releaseConnection(); //释放http连接
			
			RefundDataResponse rdResponse=new RefundDataResponse();
			XPathReader reader=new XPathReader(sysout);
			String retCode=reader.getText("/CMS/eb/pub/RetCode");
			String retMessage=reader.getText("/CMS/eb/pub/RetMsg");
			if("0".equals(retCode)){
				
				String resultPayCode=reader.getText("/CMS/eb/out/Result");
				if("1".equals(resultPayCode)){
					rdResponse.setOrderNO(reader.getText("/CMS/eb/out/OrderNum"));
					rdResponse.setSerialNo(reader.getText("/CMS/eb/out/RepReserved2"));
					response.setResultCodeAndMessageAndResult(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMessage(), rdResponse);
				}else{
					String failMessage=reader.getText("/CMS/eb/out/RepReserved1")+"||"+reader.getText("/CMS/eb/out/RepReserved2");
					response.setResultCodeAndMessage(ResponseEnum.FAILURE.getCode(), "退货失败－>"+failMessage);
				}
			}else{
				response.setResultCodeAndMessage(ResponseEnum.FAILURE.getCode(), retMessage);
			}
		}catch(Exception ex){
			response.setResultCodeAndMessage(ResponseEnum.ICBC_ORDER__FAILURE.getCode(), "工行退款失败:"+ex.getMessage());
			logger.error("工行退款失败"+refundDataVo.getOriginOrderNO()+":"+ex.getMessage(),ex);
		}
		
		return response;
	}
	
	/**
	 * 工行银企直连B2C订购指令查询
	 * @return
	 */
	public ResCommon<BEOrderQueryResponse> icbcWapB2CQuery(
			BEOrderQueryVo beOrderQueryVo) {
		
		int returnFlag = 0;
		String sysout =""; //工行返回的信息
		ResCommon<BEOrderQueryResponse> response=new ResCommon<BEOrderQueryResponse>();
		
		try {
			IcbcPayConfig config=this.getConfig();
			config.setMerId(yaml.getProperty(IcbcTrade.ICBC_PAY_MERID));
			config.setMerAcct(yaml.getProperty(IcbcTrade.ICBC_PAY_MERACCT));
			config.setPayId(yaml.getProperty(IcbcTrade.ICBC_PAY_ID));
			config.setMerchantName(yaml.getProperty(IcbcTrade.ICBC_PAY_MERNAME));
			config.setPayCis(yaml.getProperty(IcbcTrade.ICBC_PAY_CIS));
			
			config .setNcIp(yaml.getProperty(IcbcTrade.CONFIG_NC_IP));
			config.setNcPort1(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT1));
			config.setNcPort2(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT2));
			String transCode="B2CPAYINF";
			String sBankCode = "102";
			String packageID = UUIDUtil.get32UUID();
			
			String sContent="<?xml version=\"1.0\" encoding = \"GBK\"?>"+
							   "<CMS>"+
							   	"<eb>"+
							   	"<pub>"+
							   	"<TransCode>"+transCode+"</TransCode>"+
							   	"<CIS>"+config.getPayCis()+"</CIS>"+
							   	"<BankCode>"+sBankCode+"</BankCode>"+
							   	"<ID>"+config.getPayId()+"</ID>"+	
							   	"<TranDate>"+beOrderQueryVo.getTranDate()+"</TranDate>"+
							   	"<TranTime>"+beOrderQueryVo.getTranTime()+"</TranTime>"+
							   	"<fSeqno>"+packageID+"</fSeqno>"+
							   	"</pub>"+
							   	"<in>"+
							   	"<ShopType>2</ShopType>"+
							   	"<ShopCode>"+config.getMerId()+"</ShopCode>"+
							   	"<ShopAcct>"+config.getMerAcct()+"</ShopAcct>"+
							   	"<QrySerialNo></QrySerialNo>"+
							   	"<QryOrderNum>"+convertNullToEmptyStr(beOrderQueryVo.getOrderNO())+"</QryOrderNum>"+	
							   	"<BeginDate>"+convertNullToEmptyStr(beOrderQueryVo.getBeginOrderDate())+"</BeginDate>"+
							   	"<EndDate>"+convertNullToEmptyStr(beOrderQueryVo.getEndOrderDate())+"</EndDate>"+
							   	"<BeginTime>"+convertNullToEmptyStr(beOrderQueryVo.getBeginOrderTime())+"</BeginTime>"+
							   	"<EndTime>"+convertNullToEmptyStr(beOrderQueryVo.getEndOrderTime())+"</EndTime>"+
							   	"<ResultType></ResultType>"+
							   	"<NextTag></NextTag>"+
							   	"<ReqReserved1></ReqReserved1>"+
							   	"<ReqReserved2></ReqReserved2>"+	
							   	"</in>"+
							   	"</eb>"+
							   	"</CMS>";
			logger.info("工行银企直连查询->"+beOrderQueryVo.getOrderNO()+"，明文->"+sContent);
			
			String urlStr1 = "http://" + config.getNcIp() + ":" + config.getNcPort1()+"/servlet/ICBCCMPAPIReqServlet?userID="
			+config.getPayId()+"&PackageID="
			+packageID+"&SendTime="
			+beOrderQueryVo.getTranDate()+beOrderQueryVo.getTranTime();
			
			HttpClient myclient = new HttpClient(); //构建http客户端	
			PostMethod mypost = new PostMethod(urlStr1); //加密端口
		
			mypost.addParameter("Version", "0.0.0.1");
			mypost.addParameter("TransCode", transCode);
			mypost.addParameter("BankCode", sBankCode);
			mypost.addParameter("GroupCIS", config.getPayCis());
			mypost.addParameter("ID", config.getPayId());
			mypost.addParameter("PackageID", packageID);
			mypost.addParameter("Cert", "");
			mypost.addParameter("reqData", sContent);
			
			logger.info("工行银企直连查询->"+beOrderQueryVo.getOrderNO()+"->开始发送到加密端...");
			returnFlag = myclient.executeMethod(mypost); //获得http返回码
			logger.info("工行银企直连退款->"+beOrderQueryVo.getOrderNO()+"->已返回数据...");
			
			if(returnFlag!=200){
				response.setResultCodeAndMessage(ResponseEnum.ICBC_BE_ORDER_QUERY_FAILURE.getCode(), "工行银企直连查询失败!");
				return response;
			}
			
			try {
				String postResult = mypost.getResponseBodyAsString();
				logger.info("工行银企直连查询"+beOrderQueryVo.getOrderNO()+"->返回数据如下:" + new String(postResult.getBytes("ISO8859-1"),"gb2312"));
				postResult = postResult.substring(8);
				byte[] decodeResult = Tools.getFromBASE64(postResult);
				sysout = new String(decodeResult,"GBK");
				logger.info("工行银企直连查询"+beOrderQueryVo.getOrderNO()+"->base64解码如下:" +sysout);

			} catch (Exception e) {
				logger.error("工行银企直连退款解释返回数据异常"+beOrderQueryVo.getOrderNO(),e);
				response.setResultCodeAndMessage(ResponseEnum.ICBC_BE_ORDER_QUERY_FAILURE.getCode(), "工行银企直连退款解释返回数据异常!");
				return response;
			}
			mypost.releaseConnection(); //释放http连接
			
			
			response.setResultCodeAndMessage(ResponseEnum.FAILURE.getCode(), "fail not manager");
			
		}catch(Exception ex){
			response.setResultCodeAndMessage(ResponseEnum.ICBC_BE_ORDER_QUERY_FAILURE.getCode(), "工行银企直连失败:"+ex.getMessage());
			logger.error("工行银企直连查询失败"+beOrderQueryVo.getOrderNO()+":"+ex.getMessage(),ex);
		}
		
		return response;
	}
	
	
	/**
	 * 工行银企直连B2C查询
	 * @return
	 */
	public ResCommon<RefundDataQueryResponse> icbcWapB2CRefundQuery(
			RefundDataQueryVo refundDataQueryVo) {
		
		int returnFlag = 0;
		String sysout =""; //工行返回的信息
		ResCommon<RefundDataQueryResponse> response=new ResCommon<RefundDataQueryResponse>();
		
		try {
			IcbcPayConfig config=this.getConfig();
			config.setMerId(yaml.getProperty(IcbcTrade.ICBC_PAY_MERID));
			config.setMerAcct(yaml.getProperty(IcbcTrade.ICBC_PAY_MERACCT));
			config.setPayId(yaml.getProperty(IcbcTrade.ICBC_PAY_ID));
			config.setMerchantName(yaml.getProperty(IcbcTrade.ICBC_PAY_MERNAME));
			config.setPayCis(yaml.getProperty(IcbcTrade.ICBC_PAY_CIS));
			
			config .setNcIp(yaml.getProperty(IcbcTrade.CONFIG_NC_IP));
			config.setNcPort1(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT1));
			config.setNcPort2(yaml.getProperty(IcbcTrade.CONFIG_NC_PORT2));
			String transCode="B2CEJEINF";
			String sBankCode = "102";
			String packageID = UUIDUtil.get32UUID();
			
			String sContent="<?xml version=\"1.0\" encoding = \"GBK\"?>"+
							"<CMS>"+
							"<eb>"+
							"<pub>"+
							"<TransCode>"+transCode+"</TransCode>"+
							"<CIS>"+config.getPayCis()+"</CIS>"+
							"<BankCode>"+sBankCode+"</BankCode>"+
							"<ID>"+config.getPayId()+"</ID>"+	
							"<TranDate>"+refundDataQueryVo.getTranDate()+"</TranDate>"+
							"<TranTime>"+refundDataQueryVo.getTranTime()+"</TranTime>"+
							"<fSeqno>"+packageID+"</fSeqno>"+
							"</pub>"+
							"<in>"+
							"<Ordertype>0</Ordertype>"+//0：退货 1：返还 2：转付
							"<ShopType>2</ShopType>"+//1：B2B商城  2：B2C商城 3：C2C商城
							"<ShopCode>"+config.getMerId()+"</ShopCode>"+
							"<ShopAcct>"+config.getMerAcct()+"</ShopAcct>"+
							"<QrySerialNo></QrySerialNo>"+
							"<QryOrderNum>"+convertNullToEmptyStr(refundDataQueryVo.getOrderNO())+"</QryOrderNum>"+
						  	"<BeginDate>"+convertNullToEmptyStr(refundDataQueryVo.getBeginOrderDate())+"</BeginDate>"+
						   	"<EndDate>"+convertNullToEmptyStr(refundDataQueryVo.getEndOrderDate())+"</EndDate>"+
							"<BeginTime></BeginTime>"+
							"<EndTime></EndTime>"+
							"<ResultType></ResultType>"+
							"<NextTag></NextTag>"+
							"<ReqReserved1></ReqReserved1>"+
							"<ReqReserved2></ReqReserved2>"+
							"</in>"+
							"</eb>"+
							"</CMS>";
			logger.info("工行银企直连B2C查询->"+refundDataQueryVo.getOrderNO()+"，明文->"+sContent);
			
			String urlStr1 = "http://" + config.getNcIp() + ":" + config.getNcPort1()+"/servlet/ICBCCMPAPIReqServlet?userID="
			+config.getPayId()+"&PackageID="
			+packageID+"&SendTime="
			+refundDataQueryVo.getTranDate()+refundDataQueryVo.getTranTime();
			
			HttpClient myclient = new HttpClient(); //构建http客户端	
			PostMethod mypost = new PostMethod(urlStr1); //加密端口
		
			mypost.addParameter("Version", "0.0.0.1");
			mypost.addParameter("TransCode", transCode);
			mypost.addParameter("BankCode", sBankCode);
			mypost.addParameter("GroupCIS", config.getPayCis());
			mypost.addParameter("ID", config.getPayId());
			mypost.addParameter("PackageID", packageID);
			mypost.addParameter("Cert", "");
			mypost.addParameter("reqData", sContent);
			
			logger.info("工行银企直连B2C查询->"+refundDataQueryVo.getOrderNO()+"->开始发送到...");
			returnFlag = myclient.executeMethod(mypost); //获得http返回码
			logger.info("工行银企直连B2C查询->"+refundDataQueryVo.getOrderNO()+"->已返回数据...");
			
			if(returnFlag!=200){
				response.setResultCodeAndMessage(ResponseEnum.ICBC_REFUND_ORDER_QUERY_FAILURE.getCode(), "工行退款发送到中转到服务器失败!");
				return response;
			}
			
			try {
				String postResult = mypost.getResponseBodyAsString();
				logger.info("工行银企直连B2C查询->"+refundDataQueryVo.getOrderNO()+"->返回数据如下:" + new String(postResult.getBytes("ISO8859-1"),"gb2312"));
				postResult = postResult.substring(8);
				byte[] decodeResult = Tools.getFromBASE64(postResult);
				sysout = new String(decodeResult,"GBK");
				logger.info("工行银企直连B2C查询->"+refundDataQueryVo.getOrderNO()+"->base64解码如下:" +sysout);

				RefundDataQueryResponse refundDataQueryResponse=new RefundDataQueryResponse();
				XPathReader reader=XPathReader.createXmlPathReaderByXml(sysout);
				if(reader.findXPath("/CMS/eb/out/rd/SerialNo")){
					refundDataQueryResponse.setOrderAmt(reader.getText("/CMS/eb/out/rd/OrderAmt"));
					refundDataQueryResponse.setOrderNo(reader.getText("/CMS/eb/out/rd/OrderNum"));
					refundDataQueryResponse.setRecAccName(reader.getText("/CMS/eb/out/rd/RecAccNameCN"));
					refundDataQueryResponse.setRecAccNo(reader.getText("/CMS/eb/out/rd/RecAccNo"));
					refundDataQueryResponse.setRefundState(reader.getText("/CMS/eb/out/rd/Result"));
					refundDataQueryResponse.setSerialNo(reader.getText("/CMS/eb/out/rd/SerialNo"));
					refundDataQueryResponse.setTranAmt(reader.getText("/CMS/eb/out/rd/TranAmt"));
					refundDataQueryResponse.setTranTime(reader.getText("/CMS/eb/out/rd/TranTime"));
					response.setResultCodeAndMessageAndResult("0", "查询成功",refundDataQueryResponse);
				}else{
					response.setResultCodeAndMessage(ResponseEnum.ICBC_REFUND_ORDER_QUERY_FAILURE.getCode(), "当笔退款订单没查询到");
				}
			} catch (Exception e) {
				logger.error("工行银企直连B2C查询解释返回数据异常"+refundDataQueryVo.getOrderNO(),e);
				response.setResultCodeAndMessage(ResponseEnum.ICBC_REFUND_ORDER_QUERY_FAILURE.getCode(), "工行银企直连B2C查询解释返回数据异常!");
				return response;
			}
			mypost.releaseConnection(); //释放http连接
		}catch(Exception ex){
			response.setResultCodeAndMessage(ResponseEnum.ICBC_REFUND_ORDER_QUERY_FAILURE.getCode(), "工行银企直连B2C查询失败:"+ex.getMessage());
			logger.error("工行银企直连B2C查询失败->"+refundDataQueryVo.getOrderNO()+":"+ex.getMessage(),ex);
		}
		
		return response;
	}
	
	private String convertNullToEmptyStr(String str){
		if(StringUtils.isEmpty(str)){
			return "";
		}
		return str;
	}
	
	public String getIcbcErrorMessage(String code){
		String errorMessage="";
		if(code.equals("40972")){
			errorMessage="API查询的订单不存在";
		}
		else if(code.equals("40973")){
			errorMessage="API查询过程中系统异常";
		}
		else if(code.equals("40976")){
			errorMessage="API查询系统异常";
		}
		else if(code.equals("40977")){
			errorMessage="商户证书信息错";
		}
		else if(code.equals("40978")){
			errorMessage="解包商户请求数据报错";
		}
		else if(code.equals("40979")){
			errorMessage="查询的订单不存在";
		}
		else if(code.equals("40980")){
			errorMessage="API查询过程中系统异常";
		}
		else if(code.equals("40981")){
			errorMessage="给商户打包返回数据错";
		}
		else if(code.equals("40982")){
			errorMessage="系统错误";
		}
		else if(code.equals("40983")){
			errorMessage="查询的订单不唯一";
		}
		else if(code.equals("40987")){
			errorMessage="请求数据中接口名错误";
		}
		else if(code.equals("40947")){
			errorMessage="商户代码或者商城账号有误";
		}
		else if(code.equals("40948")){
			errorMessage="商城状态非法";
		}
		else if(code.equals("40949")){
			errorMessage="商城类别非法";
		}
		else if(code.equals("40950")){
			errorMessage="商城应用类别非法";
		}
		else if(code.equals("40951")){
			errorMessage="商城应用类别非法";
		}
		else if(code.equals("40952")){
			errorMessage="商户证书id未绑定或商城账号绑定";
		}
		else if(code.equals("40953")){
			errorMessage="商户id权限非法";
		}
		else if(code.equals("40954")){
			errorMessage="检查商户状态时数据库异常";
		}
		else if(code.equals("42022")){
			errorMessage="业务类型上送有误";
		}
		else if(code.equals("42023")){
			errorMessage="商城种类上送有误";
		}
		else if(code.equals("42020")){
			errorMessage="ID未开通汇总记账清单功能";
		}
		else if(code.equals("42021")){
			errorMessage="汇总记账明细清单功能已到期";
		}
		else if(code.equals("40990")){
			errorMessage="商户证书格式错误";
		}
		else if(code.equals("41160")){
			errorMessage="商户未开通外卡支付业务";
		}
		else if(code.equals("41161")){
			errorMessage="商户id对商城账号没有退货权限";
		}
		else if(code.equals("41177")){
			errorMessage="外卡的当日退货必须为全额退货";
		}
		else if(code.equals("26012")){
			errorMessage="找不到记录";
		}
		else if(code.equals("26002")){
			errorMessage="数据库操作异常";
		}
		else if(code.equals("26034")){
			errorMessage="退货交易重复提交";
		}
		else if(code.equals("26036")){
			errorMessage="更新支付表记录失败";
		}
		else if(code.equals("26042")){
			errorMessage="退货对应的支付订单未清算，不能退货";
		}
		else if(code.equals("41996")){
			errorMessage="主机超时或接口报错";
		}
		return errorMessage;
	}
	
	private static HostnameVerifier hnv = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	/**
	 * 
	 * 信任所有证书
	 */

	private static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
		public void checkServerTrusted(X509Certificate[] certs, String authType) {
			return;
		}
		public void checkClientTrusted(X509Certificate[] certs, String authType) {
			return;
		}
	} };

}
